/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.javlov.example.grid.landmarks;

import java.awt.Point;
import java.util.List;

import net.javlov.AbstractOption;
import net.javlov.Action;
import net.javlov.LearningRate;
import net.javlov.Option;
import net.javlov.Policy;
import net.javlov.State;
import net.javlov.example.grid.Direction;

public class ReachLandmarkOption extends AbstractOption<double[]> {

	protected int dist;
	protected Point endPoint;
	protected List<Action> actions;
	
	public ReachLandmarkOption(String name, int dist, Point end, List<Action> actionPool) {
		super(name);
		this.dist = dist;
		endPoint = end;
		actions = actionPool;
	}
	
	@Override
	public double getBeta(State<? extends double[]> s) {
		double[] data = s.getData();
		if ( data[0] == endPoint.x && data[1] == endPoint.y )
			return 1;
		if ( Math.abs(data[0] - endPoint.x) + Math.abs(data[1] - endPoint.y) <= dist )
			return 0;
		return 1;
	}

	@Override
	public boolean isEligible(State<? extends double[]> s) {
		return getBeta(s) < 1;
	}
	
	@Override
	public void update(State<? extends double[]> s, Option<double[]> o, double update) {
		//Non-learning option		
	}

	@Override
	public Action<double[]> doStep(State<? extends double[]> s, double reward) {
		double[] data = s.getData();
		
		if ( data[0] == endPoint.x && data[1] == endPoint.y ) {
			setFinished();
			return null;
		}
			
		int xdir = (int)Math.signum(endPoint.x - data[0]),
			ydir = (int)Math.signum(endPoint.y - data[1]);
		
		int dirid;
		if ( actions.size() == 4 ) { //diagonal move not allowed
			if ( Math.abs(xdir) == Math.abs(ydir) ) { //both |1|
				if ( Math.random() < 0.5 )
					xdir = 0;
				else
					ydir = 0;
					
			}
			dirid = Direction.get(xdir, ydir).getID();
			return actions.get(dirid/2);
		}
		dirid = Direction.get(xdir, ydir).getID();
		return actions.get(dirid);
	}

	@Override
	public Action<double[]> firstStep(State<? extends double[]> s) {
		finished = false;
		return doStep(s, 0);
	}

	@Override
	public Policy<double[]> getPolicy() {
		return null;
	}

	@Override
	public void setPolicy(Policy<double[]> p) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public LearningRate getLearnRate() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setLearnRate(LearningRate rate) {
		// TODO Auto-generated method stub
		
	}
}
